package com.shiyu.exam.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shiyu.exam.entity.Category;
import com.shiyu.exam.entity.Question;
import com.shiyu.exam.exception.ExamException;
import com.shiyu.exam.mapper.CategoryMapper;
import com.shiyu.exam.mapper.QuestionMapper;
import com.shiyu.exam.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Slf4j
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {

    @Autowired
    private QuestionMapper questionMapper;


    // 获取分类下的题目数量的方法
    private void getQuestionCount(List<Category> categories) {
        // 获取分类下的题目数量
        List<Map<Long, Long>> countList = questionMapper.getCategoryCount();
        System.out.println("countList = " + countList);
        //将List<Map<Long, Long>> 转换为Map<Long, Long>
        Map<Long, Long> collect = countList.stream().collect(Collectors.toMap(
                map -> map.get("category_id"),
                map -> map.get("count")
        ));
        System.out.println("collect = " + collect);
        categories.forEach(category -> {
            Long count = collect.getOrDefault(category.getId(), 0L);
            category.setCount(count);
        });
    }


    // 构建分类树结构的方法
    private List<Category> buildCategoryTree(List<Category> categories) {
        // 根据父分类ID进行分组
        Map<Long, List<Category>> collect = categories.stream()
                .collect(Collectors.groupingBy(Category::getParentId));
        // 遍历所有分类
        categories.forEach(category -> {
            // 获取当前的分类id
            Long id = category.getId();
            // 获取当前分类下的子分类
            List<Category> orDefault = collect.getOrDefault(id, new ArrayList<>());
            category.setChildren(orDefault);
            // 获取当前子分类下的题目数量之和
            long sum = orDefault.stream().mapToLong(c -> c.getCount() != null ? c.getCount() : 0L).sum();
            // 获取当前类型的题目 数量
            Long count = category.getCount();
            // 设置当前类型的题目数量
            category.setCount(count + sum);
        });
        // 获取根节点，根节点的父ID为0
        List<Category> categoryTree = categories.stream().filter(category -> category.getParentId() == 0).collect(Collectors.toList());
        return categoryTree;
    }

    // 判断分类名称是否已经存在的方法
    private void isExist(Category category, LambdaQueryWrapper<Category> eq1) {
        Category category1 = baseMapper.selectOne(eq1);
        //如果同名分类存在
        if (category1 != null) {
            //获取父级分类id
            Long parentId = category.getParentId();
            //根据分类id获取分类
            Category parent = baseMapper.selectById(parentId);
            //判断父级分类是否存在，如果不存在，则设置返回错误信息为根节点
            String parentName = parent == null ? "根节点" : parent.getName();
            //抛出异常
            throw new ExamException(111,"父分类<"+parentName+">下已存在<"+category1.getName()+">分类，请重新输入分类名称");
        }
    }

    //========================================================================================================================

    /**
     * 功能描述：获取所有分类和题目数量
     *
     * @return {@link List }<{@link Category }>
     * @author shiyu
     * @date 2025/10/10
     */
    @Override
    public List<Category> getCategoriesAndCount() {
        // 获取所有分类
        LambdaQueryWrapper<Category> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 排序
        LambdaQueryWrapper<Category> orderByAsc = categoryLambdaQueryWrapper.orderByAsc(Category::getSort);
        // 查询
        List<Category> categories = baseMapper.selectList(orderByAsc);
        getQuestionCount(categories);
        System.out.println("categories = " + categories);
        return categories;
    }


    /**
     * 功能描述：获取分类树结构
     *
     * @return {@link List }<{@link Category }>
     * @author shiyu
     * @date 2025/10/10
     */
    @Override
    public List<Category> getCateTree() {
        // 创建查询条件
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
        // 根据排序进行升序
        LambdaQueryWrapper<Category> orderByAsc = queryWrapper.orderByAsc(Category::getSort);
        // 根据父分类ID进行分组
        List<Category> categories = baseMapper.selectList(orderByAsc);
        //获取每个分类下的题目数量
        getQuestionCount(categories);
        // 构建分类树结构
        List<Category> categoryTree = buildCategoryTree(categories);
        return categoryTree;
    }


    /**
     * 功能描述：添加新的分类
     *
     * @param category 类别
     * @author shiyu
     * @date 2025/10/10
     */
    @Override
    public void saveCategory(Category category) {
        //首先判断分类名称是否已经存在
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
        //查询是否有同名分类
        //获取所有的分类名称---->可以进行链式调用，eq. eq
        LambdaQueryWrapper<Category> eq = queryWrapper.eq(Category::getName, category.getName());
        //获取同名分类
        LambdaQueryWrapper<Category> eq1 = eq.eq(Category::getParentId, category.getParentId());
        //判断同名分类是否存在
        isExist(category, eq1);
        baseMapper.insert(category);
    }


    /**
     * 功能描述：修改分类--> 更新
     *
     * @param category 类别
     * @author shiyu
     * @date 2025/10/10
     */
    @Override
    public void updateCategory(@NotNull Category category) {
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
        //首先获取除了自己以外的父分类下的其他分类名称
        LambdaQueryWrapper<Category> ne = queryWrapper
                //获取父分类下的所有的分类
                .eq(Category::getParentId, category.getParentId())
                //获取所有的分类名称
                .eq(Category::getName, category.getName())
                //除去自己的分类名称
                .ne(Category::getId, category.getId());

        //判断新更新的名称是否有同名分类
        isExist(category, ne);
        // 2. 通过检查，真正更新
        baseMapper.updateById(category);
    }


    /**
     * 功能描述：删除分类
     *
     * @param id id
     * @author shiyu
     * @date 2025/10/10
     */
    @Override
    public void deleteCategory(Long id) {
        // 判断该分类下是否有子分类
        Long l = baseMapper.selectCount(new LambdaQueryWrapper<Category>().eq(Category::getParentId, id));
        if (l > 0) {
            throw new ExamException(111, "该分类下有子分类，请先删除子分类");
        }
        // 判断该分类下是否有题目
        Long l1 = questionMapper.selectCount(new LambdaQueryWrapper<Question>().eq(Question::getCategoryId, id));
        if (l1 > 0) {
            throw new ExamException(111, "该分类下有题目，请先删除题目");
        }
        //都满足条件，可以删除
        baseMapper.deleteById(id);
    }
}